package com.wk.demo;

/**
 * 内部类方法可以访问该类定义所在作用域中的数据，包括被 private 修饰的私有数据
 * 内部类可以对同一包中的其他类隐藏起来
 * 内部类可以解决java 单继承的缺陷
 * 当我们想要定义一个回调函数却不想写大量代码的时候我们可以选择使用匿名内部类来实现
 * @author wukai
 * @date 2023/5/19 10:50
 * 1.可以无条件地访问外围类的所有元素
 * 为什么可以引用：内部类虽然和外部类写在同一个文件中， 但是编译完成后， 还是生成各自的class文件，内部类通过this访问外部类的成员。
 * 编译器自动为内部类添加一个成员变量， 这个成员变量的类型和外部类的类型相同， 这个成员变量就是指向外部类对象(this)的引用；
 * 编译器自动为内部类的构造方法添加一个参数， 参数的类型是外部类的类型， 在构造方法内部使用这个参数为内部类中添加的成员变量赋值；
 * 在调用内部类的构造函数初始化内部类对象时，会默认传入外部类的引用。
 * 2. 实现掩藏,内部类可以用private , protected修饰
 * 我们使用 private 来修饰内部类的时候这个类就对外隐藏了。这看起来没什么作用，但是当内部类实现某个接口的时候，在进行向上转型，对外部来说，就完全隐藏了接口的实现了
 * 3. 可以实现多重继承
 * 我们知道 java 是不允许使用 extends 去继承多个类的。内部类的引入可以很好的解决这个事情。
 * 我的理解 Java只能继承一个类这个学过基本语法的人都知道，而在有内部类之前它的多重继承方式是用接口来实现的。
 * 但使用接口有时候有很多不方便的地方。比如我们实现一个接口就必须实现它里面的所有方法。
 * 而有了内部类就不一样了。它可以使我们的类继承多个具体类或抽象类
 * 4. 通过匿名内部类来优化简单的接口实现 创建线程
 *
 *  内部类与外部类关系：
 *  对于非静态内部类，内部类的创建依赖外部类的实例对象，在没有外部类实例之前是无法创建内部类的
 * 内部类是一个相对独立的实体，与外部类不是is-a关系
 * 创建内部类的时刻并不依赖于外部类的创建
 *
 * 静态内部类可以有静态变量  非静态内部类不能定义静态变量
 * 静态内部类只能访问外部类的静态变量 ，不能访问非静态变量，非静态内部类都可以访问
 */
public class InternalClass {
    private String data = "外部类私有数据";
    // 从这段代码里面我只知道OuterClass的getInner()方法能返回一个InnerInterface接口实例
    // 但我并不知道这个实例是这么实现的。而且由于InnerClass是private的，
    // 所以我们如果不看代码的话根本看不到这个具体类的名字，所以说它可以很好的实现隐藏。
    public FlyInterface getInner(){
        return new InnerClass();
    }
    public String getName(){
        return new InnerOne().name();
    }
    public int getAge(){
        return new InnerTwo().age();
    }

    private class InnerClass implements FlyInterface{
        public InnerClass(){
            System.out.println("内部类构造器");
            System.out.println(data);
        }

        @Override
        public void fly() {
            System.out.println("inner class fly,内部类掩藏");
        }
    }
    // 间接实现了多重继承
    private class InnerOne extends ExampleOne{
        public String name(){
            return super.getName();
        }
    }
    private class InnerTwo extends ExampleTwo{
        public int age(){
            return super.getAge();
        }
    }

//    public static void main(String[] args) {
//        InternalClass out = new InternalClass();
//        FlyInterface inner = out.getInner();
//        inner.fly();
//        System.out.println(out.getName());
//        System.out.println(out.getAge());
//        // 匿名内部类，等价于
//        // class Anomymous implements Runnable {
//        //    public void run() {
//        //    }
//        //}
//        //Runnable rn = new Anomymous();
//        Thread tr = new Thread(new Runnable() {
//            @Override
//            public void run() {
//
//            }
//        });
//        tr.start();
//    }
    public static void main(String[] args) {
        // 内部类创建方式
        InnerClass innerClass = new InternalClass().new InnerClass();

        InternalClass out = new InternalClass();
        InnerClass innerClass2 = out.new InnerClass();
    }
}
